#                                                              -*-mode: perl-*-

$description = "Test various forms of the GNU Make 'include' command.";

$details = "\
Test include, -include, sinclude and various regressions involving them.
Test extra whitespace at the end of the include, multiple -includes and
sincludes (should not give an error) and make sure that errors are reported
for targets that were also -included.";

create_file('incl.mk', "ANOTHER: ; \@echo This is another included makefile\n");

run_make_test(qq!#Extra space at the end of the following file name
include incl.mk    ! . q!
all: ; @echo There should be no errors for this makefile.

-include nonexistent.mk
-include nonexistent.mk
sinclude nonexistent.mk
sinclude nonexistent-2.mk
-include makeit.mk
sinclude makeit.mk

error: makeit.mk
!,
              "all", "There should be no errors for this makefile.\n");

run_make_test(undef, "ANOTHER", "This is another included makefile\n");

unlink('incl.mk');

# Try to build the "error" target; this will fail since we don't know
# how to create makeit.mk, but we should also get a message (even though
# the -include suppressed it during the makefile read phase, we should
# see one during the makefile run phase).

run_make_test
  ('
-include foo.mk
error: foo.mk ; @echo $@
',
   '',
   "#MAKE#: *** No rule to make target 'foo.mk', needed by 'error'.  Stop.\n",
   512
  );

# The same as above with an additional include directory.

mkdir('hellod', 0777);

run_make_test
  ('
-include foo.mk
error: foo.mk ; @echo $@
',
   '-Ihellod',
   "#MAKE#: *** No rule to make target 'foo.mk', needed by 'error'.  Stop.\n",
   512
  );

rmdir('hellod');

# Make sure that target-specific variables don't impact things.  This could
# happen because a file record is created when a target-specific variable is
# set.

run_make_test
  ('
bar.mk: foo := baz
-include bar.mk
hello: ; @echo hello
',
   '',
   "hello\n"
  );


# Test inheritance of dontcare flag when rebuilding makefiles.
#
run_make_test('
.PHONY: all
all: ; @:

-include foo

foo: bar; @:
', '', '');


# Make sure that we don't die when the command fails but we dontcare.
# (Savannah bug #13216).
#
run_make_test('
.PHONY: all
all:; @:

-include foo

foo: bar; @:

bar:; @exit 1
', '', '');

# Check include, sinclude, -include with no filenames.
# (Savannah bug #1761).

run_make_test('
.PHONY: all
all:; @:
include
-include
sinclude', '', '');


# Test that the diagnostics is issued even if the target has been
# tried before with the dontcare flag (direct dependency case).
#
run_make_test('
-include foo

all: bar

foo: baz
bar: baz
',
'',
"#MAKE#: *** No rule to make target 'baz', needed by 'bar'.  Stop.\n",
512);

# Test that the diagnostics is issued even if the target has been
# tried before with the dontcare flag (indirect dependency case).
#
run_make_test('
-include foo

all: bar

foo: baz
bar: baz
baz: end
',
'',
"#MAKE#: *** No rule to make target 'end', needed by 'baz'.  Stop.\n",
512);

# Test include of make-able file doesn't show an error (Savannah #102)
run_make_test(q!
.PHONY: default
default:; @echo DONE

inc1:; echo > $@
include inc1
include inc2
inc2:; echo > $@
!,
              '', "echo > inc1\necho > inc2\nDONE\n");

rmfiles('inc1', 'inc2');

# Test include of make-able file doesn't show an error.
# Specify an additional include directory.

mkdir('hellod', 0777);

run_make_test(q!
.PHONY: default
default:; @echo DONE

inc1:; echo > $@
include inc1
include inc2
inc2:; echo > $@
!,
              '-Ihellod', "echo > inc1\necho > inc2\nDONE\n");

rmfiles('inc1', 'inc2');

# Test include of make-able file doesn't show an error.
# inc1 and inc2 are present in the specified include directory.
touch('hellod/inc1');
touch('hellod/inc2');

run_make_test(q!
.PHONY: default
default:; @echo DONE

inc1:; echo > $@
include inc1
include inc2
inc2:; echo > $@
!,
              '-Ihellod', "DONE\n");

rmfiles('inc1', 'inc2', 'hellod/inc1', 'hellod/inc2');

rmdir('hellod');

# No target gets correct error
run_make_test("\n", '', '#MAKE#: *** No targets.  Stop.', 512);

# No target in included file either, still gets correct error.
touch('inc1.mk');
run_make_test('include inc1.mk', '', '#MAKE#: *** No targets.  Stop.', 512);
rmfiles('inc1.mk');

# Include same file multiple times

run_make_test(q!
default:; @echo DEFAULT
include inc1
inc1:; echo > $@
include inc1
!,
              '', "echo > inc1\nDEFAULT\n");

rmfiles('inc1');

if (defined $ERR_no_such_file) {

    # Test that the diagnostics is issued even if the target has been
    # tried before with the dontcare flag (include/-include case).
    #
    run_make_test('
include bar
-include foo

all:

foo: baz
bar: baz
baz: end
',
'',
                  "#MAKEFILE#:2: bar: $ERR_no_such_file\n#MAKE#: *** No rule to make target 'end', needed by 'baz'.  Stop.\n",
                  512);

    # Test include of non-make-able file does show an error (Savannah #102)
    run_make_test(q!
.PHONY: default
default:; @echo DONE

inc1:; echo > $@
include inc1
include inc2
!,
                  '', "echo > inc1\n#MAKEFILE#:7: inc2: $ERR_no_such_file\n#MAKE#: *** No rule to make target 'inc2'.  Stop.\n", 512);

    rmfiles('inc1');

    # Included file has a prerequisite that fails to build

    run_make_test(q!
default:; @echo DEFAULT
include inc1
inc1: foo; echo > $@
foo:; exit 1
!,
                  '', "exit 1\n#MAKEFILE#:3: inc1: $ERR_no_such_file\n#MAKE#: *** [#MAKEFILE#:5: foo] Error 1\n", 512);

    rmfiles('inc1');

    # Included file has a prerequisite we don't know how to build

    run_make_test(q!
default:; @echo DEFAULT
include inc1
inc1: foo; echo > $@
!,
                  '', "#MAKEFILE#:3: inc1: $ERR_no_such_file\n#MAKE#: *** No rule to make target 'foo', needed by 'inc1'.  Stop.\n", 512);

    rmfiles('inc1');

    # Check that included double-colon targets with no prerequisites aren't
    # built.  This should fail as hello.mk doesn't exist

    run_make_test(q!
.PHONY: default
default:;@echo 'FOO=$(FOO)'
include hello.mk
hello.mk:: ; echo 'FOO=bar' > $@
!,
                  '', "#MAKEFILE#:4: hello.mk: $ERR_no_such_file", 512);

    # Check that included phony targets aren't built.
    # This should fail as hello.mk doesn't exist

    run_make_test(q!
.PHONY: default
default:;@echo 'FOO=$(FOO)'
include hello.mk
hello.mk: ; echo 'FOO=bar' > $@
.PHONY: hello.mk
!,
                  '', "#MAKEFILE#:4: hello.mk: $ERR_no_such_file", 512);
}

if (defined $ERR_unreadable_file) {
    # Including files that can't be read should show an error
    unlink('inc1');
    create_file('inc1', 'FOO := foo');
    chmod 0000, 'inc1';

    run_make_test(q!
include inc1
all:;@echo $(FOO)
!,
                  '', "#MAKEFILE#:2: inc1: $ERR_unreadable_file\n#MAKE#: *** No rule to make target 'inc1'.  Stop.", 512);

    # Including files that can't be read should show an error, even when there
    # is a readable file in a subsequent include directory.
    mkdir('hellod', 0777);
    touch("hellod/inc1");

    run_make_test(q!
include inc1
all:;@echo $(FOO)
!,
                  '-Ihellod', "#MAKEFILE#:2: inc1: $ERR_unreadable_file\n#MAKE#: *** No rule to make target 'inc1'.  Stop.", 512);

    # Unreadable files that we know how to successfully recreate should work

    run_make_test(sprintf(q!
all:;@echo $(FOO)
include inc1
inc1:; @%s $@ && echo FOO := bar > $@
!, $CMD_rmfile),
                  '', "bar");

    # Unreadable files that we know how to successfully recreate should work.
    # Even when there is a readable file in an additional include directory.

    unlink('inc1');
    create_file('inc1', 'FOO := foo');
    chmod 0000, 'inc1';

    run_make_test(sprintf(q!
all:;@echo $(FOO)
include inc1
inc1:; @%s $@ && echo FOO := bar > $@
!, $CMD_rmfile),
                  '-Ihellod', "bar");

    rmfiles('inc1', 'hellod/inc1');
    rmdir('hellod');
}

# Check that the order of remaking include files is correct: should remake
# them in the same order they were encountered in the makefile.  SV 58735

run_make_test(q!
-include i1 i2
-include i3
-include i4
%:;@echo $@
all:;
!,
              '', "i1\ni2\ni3\ni4\n#MAKE#: 'all' is up to date.\n");

# Check that included files work if created after the first include failed
# https://savannah.gnu.org/bugs/?57676

run_make_test(q!
default:; @echo $(hello)
-include hello.mk
$(shell echo hello=world >hello.mk)
include hello.mk
!,
              '', "world\n");

unlink('hello.mk');

# Check that included double-colon targets with no prerequisites aren't built.
# This should succeed since hello.mk already exists

touch('hello.mk');

run_make_test(q!
.PHONY: default
default:;@echo 'FOO=$(FOO)'
include hello.mk
hello.mk:: ; echo 'FOO=bar' > $@
!,
              '', 'FOO=');

unlink('hello.mk');

# Check that included double-colon targets with no prerequisites aren't built.
# This should succeed due to -include

run_make_test(q!
.PHONY: default
default:;@echo 'FOO=$(FOO)'
-include hello.mk
hello.mk:: ; echo 'FOO=bar' > $@
!,
              '', 'FOO=');

# Check that phony targets aren't built.
# This should succeed since hello.mk already exists

touch('hello.mk');

run_make_test(q!
.PHONY: default
default:;@echo 'FOO=$(FOO)'
include hello.mk
hello.mk: ; echo 'FOO=bar' > $@
.PHONY: hello.mk
!,
              '', 'FOO=');

unlink('hello.mk');

# Check that included double-colon targets with no prerequisites aren't built.
# This should succeed due to -include

run_make_test(q!
.PHONY: default
default:;@echo 'FOO=$(FOO)'
-include hello.mk
hello.mk: ; echo 'FOO=bar' > $@
.PHONY: hello.mk
!,
              '', 'FOO=');

# SV 56301 Verify pattern rules creating optional includes.
# -k shouldn't matter when creating include files.

run_make_test(q!
all:; @echo hello
-include inc_a.mk
include inc_b.mk
%_a.mk %_b.mk:; exit 1
!,
              '', "exit 1\n#MAKEFILE#:4: failed to remake makefile 'inc_b.mk'", 512);

run_make_test(undef, '-k', "exit 1\n#MAKEFILE#:4: failed to remake makefile 'inc_b.mk'", 512);

# It seems wrong to me that this gives a different error message, but at
# least it doesn't keep going.
run_make_test(q!
all:; @echo hello
include inc_a.mk
-include inc_b.mk
%_a.mk %_b.mk:; exit 1
!,
              '', "exit 1\n#MAKEFILE#:3: inc_a.mk: $ERR_no_such_file\n#MAKE#: *** [#MAKEFILE#:5: inc_a.mk] Error 1\n", 512);

run_make_test(undef, '-k', "exit 1\n#MAKEFILE#:3: inc_a.mk: $ERR_no_such_file\n#MAKE#: *** [#MAKEFILE#:5: inc_a.mk] Error 1\n#MAKEFILE#:3: failed to remake makefile 'inc_a.mk'", 512);

# Check the default makefiles... this requires us to invoke make with no
# arguments.  Also check MAKEFILES

if ($port_type eq 'W32') {
    $defaults = "GNUmakefile\nmakefile\nMakefile\nmakefile.mak";
} else {
    $defaults = "GNUmakefile\nmakefile\nMakefile";
}

$ENV{MAKEFILES} = 'foobar barfoo';
run_make_with_options(undef, ['-E', '%:;@echo $@', '-E', 'all:;', '-E', '-include bizbaz', '-E', '-include bazbiz'], get_logfile(0));
$answer = "bizbaz\nbazbiz\nfoobar\nbarfoo\n$defaults\n#MAKE#: 'all' is up to date.\n";
&compare_output(subst_make_string($answer), &get_logfile(1));

# SV 63516
if (exists $FEATURES{'dospaths'}) {
    run_make_test(q!
include C:__foobar
%bar: ; @echo $@
all: ;
!,
                  '', "C:__foobar\n#MAKE#: 'all' is up to date.");
}

# sv 63484.
# Test that included makefiles are not intermediate.
# Here 'test.foo' is mentioned explicitly and cannot be considered
# intermediate.
utouch(-10, 'test.foo');
utouch(-5, 'test.x');
touch('test');
run_make_test(q!
.PHONY: force
include test.foo
%.foo: force; @echo force $@
%.x: %.foo; touch $@
test: test.x; touch $@
!, '', "force test.foo\n#MAKE#: 'test' is up to date.\n");

unlink('test.foo', 'test.x', 'test');

# Verify that include prefixed by TAB gives a warning

my @inctypes = ('include', '-include', 'sinclude');

touch('inc.mk');

for my $inc (@inctypes) {
    run_make_test(qq!
#TAB#$inc inc.mk
all:;\@echo hi
!,
                  '', "#MAKEFILE#:2: warning: $inc lines cannot start with TAB\nhi");
}

1;
